﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Collections;
using System.Collections.ObjectModel;

namespace PersonaLibrary.Controls
{
    /// <summary>
    /// Interaction logic for Dual.xaml
    /// </summary>
    public partial class Dual
    {
        private CollectionViewSource itemsSourceCollection = new CollectionViewSource();
        private CollectionViewSource itemsDestanationCollection = new CollectionViewSource();

        public Dual()
        {
            InitializeComponent();
            
            ItemsSource = new ObservableCollection<object>();
            ItemsDestanation = new  ObservableCollection<object>();

            itemsDestanationCollection.Source = ItemsDestanation;
            itemsSourceCollection.Source = ItemsSource;

            Binding destBinding = new Binding();
            destBinding.Source = itemsDestanationCollection;
            destanationList.SetBinding(ListBox.ItemsSourceProperty, destBinding);

            Binding sourceBinding = new Binding();
            sourceBinding.Source = itemsSourceCollection;
            sourceList.SetBinding(ListBox.ItemsSourceProperty, sourceBinding);

            Binding itemsSourceGroupBinding = new Binding();
            itemsSourceGroupBinding.Source = this.ItemsSourceGroup;
            itemsSourceGroupBinding.Mode = BindingMode.TwoWay;
        }

        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IList), typeof(Dual),
            new PropertyMetadata(ItemsSourcePropertyChanged));

        public static readonly DependencyProperty ItemsDestanationProperty = DependencyProperty.Register("ItemsDestanation", typeof(IList), typeof(Dual),
            new PropertyMetadata(ItemsDestanationPropertyChanged));
        
        public static readonly DependencyProperty SourceItemPathProperty = DependencyProperty.Register("SourceItemPath",
            typeof(string), typeof(Dual), new PropertyMetadata(string.Empty, SourceItemPathPropertyChanged));

        public static readonly DependencyProperty DestanationItemPathProperty = DependencyProperty.Register("DestanationItemPath",
            typeof(string), typeof(Dual), new PropertyMetadata(string.Empty, DestanationItemPathPropertyChanged));

        public static readonly DependencyProperty FilterPropertyNameProperty = DependencyProperty.Register("FilterPropertyName",
            typeof(string), typeof(Dual), new PropertyMetadata(""));

        private static void ItemsDestanationPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((Dual)sender).itemsDestanationCollection.Source = e.NewValue;
        }

        private static void ItemsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((Dual)sender).itemsSourceCollection.Source = e.NewValue;
        }        

        private static void SourceItemPathPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((Dual)sender).sourceList.DisplayMemberPath = e.NewValue.ToString();
        }

        private static void DestanationItemPathPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((Dual)sender).destanationList.DisplayMemberPath = e.NewValue.ToString();
        }

        public void Refresh()
        {
            if (ItemsDestanation != null && ItemsSource != null)
            {
                foreach (object item in ItemsDestanation)
                {
                    if (ItemsSource.Contains(item)) ItemsSource.Remove(item);
                }
            }
        }

        #region PublicProperties

        public IList ItemsSource
        {
            set
            {
                SetValue(ItemsSourceProperty, value);
            }
            get
            {
                return (IList)GetValue(ItemsSourceProperty);
            }
        }

        public IList ItemsDestanation
        {
            set
            {
                SetValue(ItemsDestanationProperty, value);
            }
            get
            {
                return (IList)GetValue(ItemsDestanationProperty);
            }
        }

        public ObservableCollection<System.ComponentModel.GroupDescription> ItemsSourceGroup
        {
            get
            {
                return itemsSourceCollection.GroupDescriptions;
            }
        }

        public ObservableCollection<System.ComponentModel.GroupDescription> ItemsDestanationGroup
        {
            get
            {
                return itemsDestanationCollection.GroupDescriptions;
            }
        }

        public ObservableCollection<GroupStyle> ItemsSourceHeaderTemplate
        {
            get
            {
                return sourceList.GroupStyle;
            }
        }

        public ObservableCollection<GroupStyle> ItemsDestanationHeaderTemplate
        {
            get
            {
                return destanationList.GroupStyle;
            }
        }

        public string SourceItemPath
        {
            set
            {
                SetValue(SourceItemPathProperty, value);
            }
            get
            {
                return GetValue(SourceItemPathProperty).ToString();
            }
        }

        public string DestanationItemPath
        {
            set
            {
                SetValue(DestanationItemPathProperty, value);
            }
            get
            {
                return GetValue(DestanationItemPathProperty).ToString();
            }
        }

        public string FilterPropertyName
        {
            set
            {
                SetValue(FilterPropertyNameProperty, value);
            }
            get
            {
                return GetValue(FilterPropertyNameProperty).ToString();
            }
        }

        #endregion

        #region PrivateMethods

        private void add_Click(object sender, RoutedEventArgs e)
        {
            foreach (object obj in sourceList.SelectedItems)
                ItemsDestanation.Add(obj);

            foreach (object obj in ItemsDestanation)
                if (ItemsSource.Contains(obj)) ItemsSource.Remove(obj);
        }

        private void remove_Click(object sender, RoutedEventArgs e)
        {
            foreach (object obj in destanationList.SelectedItems)
                ItemsSource.Add(obj);

            foreach (object obj in ItemsSource)
                if (ItemsDestanation.Contains(obj)) ItemsDestanation.Remove(obj);
        }

        private void removeAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (object obj in destanationList.Items)
                ItemsSource.Add(obj);

            ItemsDestanation.Clear();
        }

        private void addAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (object obj in ItemsSource)
                ItemsDestanation.Add(obj);

            ItemsSource.Clear();

            if (sourceList.SelectedItems.Count != 0) add.IsEnabled = true;
            else add.IsEnabled = false;

            removeAll.IsEnabled = true;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            add.IsEnabled = false;

            remove.IsEnabled = false;

            removeAll.IsEnabled = false;
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            sourceList.Items.Filter = delegate(object item)
            {
                if (string.IsNullOrEmpty(FilterPropertyName))
                {
                    if (item.ToString().ToLower().Contains(textBox.Text)) return true;
                    return false;
                }
                else
                {
                    System.Reflection.PropertyInfo property = item.GetType().GetProperty(FilterPropertyName);
                    if (property == null) return false;
                    if (property.GetValue(item, null).ToString().ToLower().Contains(textBox.Text)) return true;
                    else return false;
                }
            };
        }

        private void sourceList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (sourceList.SelectedItems.Count != 0) add.IsEnabled = true;
            else add.IsEnabled = false;
        }

        private void filterResult_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (destanationList.SelectedItems.Count != 0) remove.IsEnabled = true;
            else remove.IsEnabled = false;
        }

        #endregion
    }
}
